package com.qingshanhui.home_module.utils;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;

import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;


import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class Banner extends RelativeLayout implements OnPageChangeListener {
    private int loopDuration = 2000;
    private boolean isLoop;
    private int count = 0;
    private int currentItem = -1;
    private int lastPosition;
    private List<Object> mData;
    private BannerViewHolder<Object> creator;
    private List<ImageView> indicatorImages;
    private Context context;
    private BannerViewPager viewPager;
    private LinearLayout indicator;
    private BannerPagerAdapter adapter;
    private OnBannerClickListener listener;
    private static final int NUM = 5000;
    private WeakHandler handler = new WeakHandler();


    int indicatorSelectedRes = android.R.color.holo_green_light;
    int indicatorUnSelectedRes = android.R.color.darker_gray;
    int indicatorWidth = 30;
    int indicatorHeight = 5;


    public Banner setIndicatorWidthAndHeight(int indicatorWidth,int indicatorHeight) {
        this.indicatorWidth = indicatorWidth;
        this.indicatorHeight = indicatorHeight;
        return this;
    }

    public Banner setIndicatorRes(int indicatorSelectedRes,int indicatorUnSelectedRes) {
        this.indicatorSelectedRes = indicatorSelectedRes;
        this.indicatorUnSelectedRes = indicatorUnSelectedRes;
        return this;
    }


    public Banner(Context context) {
        this(context, null);
    }

    public Banner(Context context, AttributeSet attrs) {
        super(context, attrs);
//        setOrientation(VERTICAL);
        this.context = context;
        mData = new ArrayList<>();
        indicatorImages = new ArrayList<>();
        initView(context);
    }

    private void initView(Context context) {
        viewPager = new BannerViewPager(context);
        LayoutParams viewPagerParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        viewPager.setClipToPadding(false);
        viewPager.setPadding(0, 0, 0, 0);
        addView(viewPager,viewPagerParams);
        LayoutParams indicatorParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        indicatorParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        indicatorParams.topMargin = 10;
        indicator = new LinearLayout(context);
        indicator.setOrientation(LinearLayout.HORIZONTAL);
        indicator.setGravity(Gravity.CENTER);
        addView(indicator,indicatorParams);

        initViewPagerScroll();
    }

    private void initViewPagerScroll() {
        try {
            Field mField = ViewPager.class.getDeclaredField("mScroller");
            mField.setAccessible(true);
            BannerScroller scroller = new BannerScroller(viewPager.getContext());
            mField.set(viewPager, scroller);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Banner setLoopDuration(int loopDuration) {
        this.loopDuration = loopDuration;
        return this;
    }

    public Banner setData(List<?> data, BannerViewHolder<Object> creator) {
        this.mData.clear();
        this.mData.addAll(data);
        this.creator = creator;
        this.count = data.size();
        return this;
    }

    public void start() {
        if (count > 0) {
            createIndicator();
            setData();
        }
    }

    private void createIndicator() {
        indicatorImages.clear();
        indicator.removeAllViews();
        for (int i = 0; i < count; i++) {
            ImageView imageView = new ImageView(context);
            imageView.setScaleType(ScaleType.CENTER_CROP);
            LinearLayout.LayoutParams custom_params = new LinearLayout.LayoutParams(indicatorWidth,indicatorHeight);
            custom_params.leftMargin = 5;
            custom_params.rightMargin = 5;
            if (i == 0) {
                imageView.setImageResource(indicatorSelectedRes);
            } else {
                imageView.setImageResource(indicatorUnSelectedRes);
            }
            indicatorImages.add(imageView);
                indicator.addView(imageView, custom_params);
        }
    }

    public void setData() {
        isLoop = (count > 1);
        if (isLoop) {
            currentItem = NUM / 2 - ((NUM / 2) % count) + 1;
            lastPosition = 1;
        } else {
            currentItem = 0;
            lastPosition = 0;
            indicator.setVisibility(GONE);
        }
        if (adapter == null) {
            adapter = new BannerPagerAdapter();
            viewPager.addOnPageChangeListener(this);
        }
        viewPager.setAdapter(adapter);
        viewPager.setOffscreenPageLimit(count);
        viewPager.setCurrentItem(currentItem);
        if (count > 1) {
            viewPager.setScrollable(true);
        } else {
            viewPager.setScrollable(false);
        }
        if (isLoop){
            startAutoPlay();
        }
    }

    public void startAutoPlay() {
            handler.removeCallbacks(task);
            handler.postDelayed(task, loopDuration);
    }

    public void stopAutoPlay() {
            handler.removeCallbacks(task);
    }

    private final Runnable task = new Runnable() {
        @Override
        public void run() {
            if (count > 1) {
                currentItem = viewPager.getCurrentItem() + 1;
                if (isLoop) {
                    if (currentItem == adapter.getCount() - 1) {
                        currentItem = 0;
                        viewPager.setCurrentItem(currentItem, false);
                        handler.post(task);
                    } else {
                        viewPager.setCurrentItem(currentItem);
                        handler.postDelayed(task, loopDuration);
                    }
                } else {
                    if (currentItem >= adapter.getCount()) {
                        stopAutoPlay();
                    } else {
                        viewPager.setCurrentItem(currentItem);
                        handler.postDelayed(task, loopDuration);
                    }
                }
            }
        }
    };

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_OUTSIDE:
                startAutoPlay();
                break;
            case MotionEvent.ACTION_DOWN:
                stopAutoPlay();
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    private int toRealPosition(int position) {
        int realPosition;
        if (count <= 0)
            return 0;
        if (isLoop) {
            realPosition = (position - 1 + count) % count;
        } else {
            realPosition = (position + count) % count;
        }
        if (realPosition < 0)
            realPosition += count;
        return realPosition;
    }

    private class BannerPagerAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            if (mData.size() == 1) {
                return mData.size();
            } else if (mData.size() < 1) {
                return 0;
            } else {
                if (isLoop)
                    return NUM;
                else
                    return mData.size();
            }
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
            return view == object;
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, final int position) {
            if (creator == null) {
                throw new RuntimeException("[Banner] --> The layout is not specified,please set holder");
            }
            View view = creator.createView(container.getContext(), toRealPosition(position), mData.get(toRealPosition(position)));
            container.addView(view);

            if (listener != null) {
                view.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        listener.onBannerClick(mData, toRealPosition(position));
                    }
                });
            }
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        currentItem = position;
        if (isLoop) {
            indicatorImages.get((lastPosition - 1 + count) % count).setImageResource(indicatorUnSelectedRes);
            indicatorImages.get((position - 1 + count) % count).setImageResource(indicatorSelectedRes);
        } else {
            indicatorImages.get((lastPosition + count) % count).setImageResource(indicatorUnSelectedRes);
            indicatorImages.get((toRealPosition(position) + count) % count).setImageResource(indicatorSelectedRes);
        }
        lastPosition = position;
    }

    public Banner setOnBannerClickListener(OnBannerClickListener listener) {
        this.listener = listener;
        return this;
    }

    public static class BannerScroller extends Scroller {

        BannerScroller(Context context) {
            super(context);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, 800);
        }

    }


    public interface BannerViewHolder<T> {

        View createView(Context context, int position, T data);

    }

    public interface OnBannerClickListener {

        void onBannerClick(List<Object> data, int position);
    }


}
